package sg.edu.nus.iss.billing.model.account;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import sg.edu.nus.iss.billing.model.BaseModel;
import sg.edu.nus.iss.billing.model.bill.Bill;
import sg.edu.nus.iss.billing.model.bill.BillReport;
import sg.edu.nus.iss.billing.model.bill.BillingPeriod;
import sg.edu.nus.iss.billing.model.complaint.Complaint;
import sg.edu.nus.iss.billing.model.subscription.Subscription;
import sg.edu.nus.iss.billing.model.transaction.PaymentTransaction;

/**
 * @author Yeo Hee Ling, Ananda, EngKhoon
 */
public class Account extends BaseModel {

	private static final long serialVersionUID = 1L;
	private String accountNo;
	private double accountBalance;
	private String customerNRIC;
	private String customerName;
	private String billingAddress;
	private String postalCode;
	private String telephoneNo;
	private List<String> interests;
	private CustomerStatus status;
	private List<Complaint> complaints;
	private List<Subscription> subscriptions = new ArrayList<Subscription>();
	private Map<String, BillReport> billMap  = new HashMap<String, BillReport>();
	private Map<String, PaymentTransaction> paymentMap = new HashMap<String, PaymentTransaction>();

	public enum CustomerStatus {
		ACTIVE, INACTIVE
	}
	
	public Account(String accountNo, String customerNRIC, String customerName, String billingAddress, String postalCode, 
			String telephoneNo, List<String> interests, CustomerStatus status) {

		this.accountNo = accountNo;
		this.accountBalance = 0.0;
		this.customerNRIC = customerNRIC;
		this.customerName = customerName;
		this.billingAddress = billingAddress;
		this.postalCode = postalCode;
		this.telephoneNo = telephoneNo;
		this.interests = interests;
		this.status = status;
		this.subscriptions = new ArrayList<Subscription>();
		this.complaints = new ArrayList<Complaint>();
	}
	
	public Account(String accountNo) {
		this.accountNo = accountNo;
	}

	public String getAccountNo() {
		return accountNo;
	}

	public void setAccountNo(String accountNo) {
		this.accountNo = accountNo;
	}
	
	public double getAccountBalance() {
		return this.accountBalance;
	}
	
	public void setAccountBalance(double accountBalance) {
		this.accountBalance = accountBalance;
	}
	
	public String getCustomerNRIC() {
		return customerNRIC;
	}

	public void setCustomerNRIC(String customerNRIC) {
		this.customerNRIC = customerNRIC;
	}

	public String getCustomerName() {
		return customerName;
	}

	public void setCustomerName(String customerName) {
		this.customerName = customerName;
	}

	public String getBillingAddress() {
		return billingAddress;
	}

	public void setBillingAddress(String billingAddress) {
		this.billingAddress = billingAddress;
	}

	public String getPostalCode() {
		return postalCode;
	}

	public void setPostalCode(String postalCode) {
		this.postalCode = postalCode;
	}

	public String getTelephoneNo() {
		return telephoneNo;
	}

	public void setTelephoneNo(String telephoneNo) {
		this.telephoneNo = telephoneNo;
	}

	public List<String> getInterests() {
		return interests;
	}

	public void setInterests(List<String> interests) {
		this.interests = interests;
	}

	public CustomerStatus getStatus() {
		return status;
	}

	public void setStatus(CustomerStatus status) {
		this.status = status;
	}
	
	public List<Subscription> getSubscriptions() {
		return subscriptions;
	}

	public void setSubscriptions(List<Subscription> subscriptions) {
		this.subscriptions = subscriptions;
	}

	public void subscribe(Subscription subscription) {
		this.subscriptions.add(subscription);
	}
	
	public List<Complaint> getComplaints() {
		return this.complaints;
	}

	public void setComplaints(List<Complaint> complaints) {
		this.complaints = complaints;
	}
	
	public Bill generateBill(BillingPeriod period) {
		Bill bill = new Bill(this, period);
		return bill;
	}
	
	public boolean matches(Object accountObj) {
		if (!(accountObj instanceof Account))
			return false;

		Account otherAccount = (Account) accountObj;
		if(!this.accountNo.equals(otherAccount.getAccountNo()))
			return false;
		if (this.accountBalance != otherAccount.getAccountBalance())
			return false;
		if (!customerNRIC.equals(otherAccount.getCustomerNRIC()))
			return false;
		if (!customerName.equals(otherAccount.getCustomerName()))
			return false;
		if (!billingAddress.equals(otherAccount.getBillingAddress()))
			return false;
		if (!postalCode.equals(otherAccount.getPostalCode()))
			return false;
		if (!telephoneNo.equals(otherAccount.getTelephoneNo()))
			return false;
		if (!status.equals(otherAccount.getStatus()))
			return false;
		if (interests != null && otherAccount.getInterests() != null) {
			if (interests.size() == otherAccount.getInterests().size()) {
				List<String> customerInterests = otherAccount.getInterests();
				for (int n = 0; n < interests.size(); n++) {
					String innInterest = interests.get(n);
					String extInterest = customerInterests.get(n);

					if (!innInterest.equals(extInterest))
						return false;
				}
			}
			else {
				return false;
			}
		}
		else if(interests == null && otherAccount.getInterests() == null) {
			// Do Nothing.
		}
		else {
			return false;
		}
		return true;
	}

	public Map<String, BillReport> getBillMap() {
		return billMap;
	}

	public Map<String, PaymentTransaction> getPaymentMap() {
		return paymentMap;
	}

}